gadgets.util.registerOnLoadHandler(init);

var Penalty = {
  readPenaltiesData: function(data){
    if (!data || !data[Penalty.me.getId()]) 
      return {};
    return gadgets.json.parse(gadgets.util.unescapeString(data[Penalty.me.getId()].penalties));
  },
  
  readFriendsPenaltiesData: function(data){
    if (!data) 
      return {};
    var result = {};
    for (var i in data) {
      var penaltiesMap = gadgets.json.parse(gadgets.util.unescapeString(data[i].penalties));
      if (penaltiesMap) {
        result[i] = penaltiesMap[Penalty.me.getId()];
      }
    }
    return result;
  },
  
  readStats: function(data){
    if (!data)
      return {};
    var result = {};
    for (var i in data) {
      result = gadgets.json.parse(gadgets.util.unescapeString(data[i].stats));
    }
    return result;
  },
  
  createFriendsMap: function(){
    if (!this.friends) {
      return;
    }
    this.friendsMap = {};
    var self = this;
    this.friends.each(function(friend){
      self.friendsMap[friend.getId()] = friend;
    });
    
  },
  
 createHasApp: function() {
    if (!this.friends || !this.friendsWithApp || this.hasApp) {
      return;
    }
    this.hasApp = {};
    
    var self = this;
    this.friends.each(function(friend){
      self.hasApp[friend.getId()] = false;
      self.friendsWithApp.each(function(friendWithApp) {
        if (friend.getId() == friendWithApp.getId()) {
          self.hasApp[friend.getId()] = true;
        }
      });
    });
    
  },
  
  deleteAction: function (friendId, actionId) {
    for (var i = 0; i < this.myPenalties[friendId].length; i++) {
        if (this.myPenalties[friendId][i].id == actionId) {
          this.myPenalties[friendId].splice(i,1);
          this.dirty = true;
          return;
        }
     }
  }
  
};

Penalty.statusTable = {};
Penalty.statusTable['SHOOT'] = { NOTHING: 'PENDING_SHOT',
                                 SHOOT: 'PENDING_SHOT+CHALLENGE',
                                 BLOCK: 'RESULT'
                                };
Penalty.statusTable['BLOCK'] = { NOTHING: 'DELETE',
                                 SHOOT: 'RESULT',
                                 BLOCK: 'DELETE'
                                };
Penalty.statusTable['NOTHING'] = { NOTHING: 'N/A',
                                 SHOOT: 'CHALLENGE',
                                 BLOCK: 'N/A'
                                };
                                


function Action(id, type, where){
  this.id = id;
  this.type = type;
  this.where = where;
}

function init(){
  loadData();
}

function prepareDefaultDataRequest(req){
  var params = {};
  params[opensocial.DataRequest.PeopleRequestFields.FILTER] = opensocial.DataRequest.FilterType.ALL;
  req.add(req.newFetchPersonRequest('OWNER'), 'owner');
  req.add(req.newFetchPersonRequest('VIEWER'), 'viewer');
  req.add(req.newFetchPeopleRequest('OWNER_FRIENDS', params), 'ownerFriends');
  var paramsHasApp = {};
  paramsHasApp[opensocial.DataRequest.PeopleRequestFields.FILTER] = opensocial.DataRequest.FilterType.HAS_APP;
  req.add(req.newFetchPeopleRequest('OWNER_FRIENDS', paramsHasApp), 'ownerFriendsWithApp');
  req.add(req.newFetchPersonAppDataRequest('OWNER', 'penalties'), 'myPenalties');
  req.add(req.newFetchPersonAppDataRequest('OWNER_FRIENDS', 'penalties'), 'myFriendsPenalties');
  req.add(req.newFetchPersonAppDataRequest('OWNER', 'stats'), 'myStats');
}

function loadData(){
  var req = opensocial.newDataRequest();
  prepareDefaultDataRequest(req);
  req.send(onLoadData);
}

function onLoadData(data){
  Penalty.me = data.get('owner').getData();
  Penalty.friends = data.get('ownerFriends').getData();
  Penalty.friendsWithApp = data.get('ownerFriendsWithApp').getData();
  Penalty.myPenalties = Penalty.readPenaltiesData(data.get('myPenalties').getData());
  Penalty.myFriendsPenalties = Penalty.readFriendsPenaltiesData(data.get('myFriendsPenalties').getData());
  Penalty.stats.map = Penalty.readStats(data.get('myStats').getData());
  Penalty.createFriendsMap();
  Penalty.createHasApp();
  Penalty.notifications = calculateNotifications();
  //hideAll();
  penaltygame.returnToMain();
  if (!data.hadError() && Penalty.me.getId() == data.get('viewer').getData().getId()) {
    showStats(false);
    showFriends();
    showNotifications();
    storeIfDirty();
  } else {
    showStats(true);
  }
}

function calculateNotifications() {
  var notifications = [];
   
  Penalty.friends.each(function(friend) {
    var myActionsToFriend = Penalty.myPenalties ? Penalty.myPenalties[friend.getId()] : null;
    var friendPendingActions = Penalty.myFriendsPenalties ? Penalty.myFriendsPenalties[friend.getId()] : null;
    if (myActionsToFriend) {
      for (var i = 0; i < myActionsToFriend.length; i++){
        addNotifications(notifications, myActionsToFriend[i], 
            findCorrespondingAction(myActionsToFriend[i], friendPendingActions), friend);
      }
    }
    if (friendPendingActions) {
      for (var i = 0; i < friendPendingActions.length; i++){
        if (!friendPendingActions[i].processed) {
          addNotifications(notifications, 
              findCorrespondingAction(friendPendingActions[i], myActionsToFriend), 
              friendPendingActions[i], friend);
        }
      }
    }/*
    if (myActionToFriend || friendPendingAction) {
      addNotifications(notifications, myActionToFriend, friendPendingAction, friend);
    }*/
  });

  return notifications;
}

function findCorrespondingAction(action, list) {
  if (!list) {
    return null;
  }
  for (var i = 0; i < list.length; i++){
    if (action.id == list[i].id) {
      list[i].processed = true;
      return list[i];
    }
  }
  return null;
}

function addNotifications(notifications, myAction, myFriendsAction, friend){
  var notification = {};
  notification['friend'] = friend;
  notification['type'] = 'N/A';
  notification.friendsAction = myFriendsAction;
  var myType = myAction ? myAction.type :'NOTHING' ;
  var friendsType = myFriendsAction ? myFriendsAction.type :'NOTHING' ;
  var status = Penalty.statusTable[myType][friendsType];
  switch(status) {
    case 'DELETE' :
      Penalty.myPenalties[friend.getId()] = null;
      Penalty.dirty = true;
      return;
    case 'PENDING_SHOT+CHALLENGE':
      var secondNotification = {};
      secondNotification.friend = friend;
      secondNotification.type = 'CHALLENGE';
      secondNotification.friendsAction = myFriendsAction;
      notifications.push(secondNotification);
      // no break intentionally to also perform next action.
    case 'PENDING_SHOT':
      notification.type = 'PENDING_SHOT';
      break;
    case 'RESULT':
      if (myAction.type == 'SHOOT' && myFriendsAction.id == myAction.id) {
        notification.type = matchResult(myAction, myFriendsAction, friend.getId());
        Penalty.deleteAction(friend.getId(), myAction.id);
      }
      if (myAction.type == 'BLOCK') {
        if (myFriendsAction.id == myAction.id) {
          notification.type = matchResult(myAction, myFriendsAction, friend.getId());
        } else {
          Penalty.deleteAction(friend.getId(), myAction.id);
          return;
        }
      }
    break;
    default:
      notification.type = status;
  }
  notifications.push(notification);
}

function matchResult(myAction, myFriendsAction, myFriendId) {
  var result;
  if (myAction.type == 'SHOOT') {
    if (myAction.where == myFriendsAction.where) {
      result = 'FRIEND_BLOCKED';
      Penalty.stats.update(myFriendId, 'SHOOT', 'LOST');
    } else {
      result = 'MY_GOAL';
      Penalty.stats.update(myFriendId, 'SHOOT', 'WON');
	  postActivity("Scored a goal to " + Penalty.friendsMap[myFriendId].getDisplayName());
    }
  }
  if (myAction.type == 'BLOCK') {
    if (myAction.where == myFriendsAction.where) {
      result = 'ME_BLOCKED';
      Penalty.stats.update(myFriendId, 'BLOCK', 'WON');
	  postActivity("Blocked a shoot from " + Penalty.friendsMap[myFriendId].getDisplayName());
    } else {
      result = 'FRIEND_GOAL';
      Penalty.stats.update(myFriendId, 'BLOCK', 'LOST');
    }
  }
  Penalty.stats.save();
  return result;
}


function showStats(viewer){
  var statsTable = document.createElement('table');
  statsTable.width = '600px';
  statsTable.class = 'table';
  statsTable.cellspacing = '2';
  var statsTBody = document.createElement('tbody');
  statsTable.appendChild(statsTBody);
  

  addStatsRow(statsTBody, Penalty.stats.createTableNode(viewer));
  
  addStatsRow(statsTBody, Penalty.stats.createGlobalStatsNode(viewer));
  document.getElementById('stats').innerHTML = '';  
  document.getElementById('stats').appendChild(statsTable);
  document.getElementById('stats').style.display = 'block';
}


function showFriends(){
  var tbody = document.createElement('tbody');
  var friendsTable = document.createElement('table');
  friendsTable.appendChild(tbody);
  friendsTable.width = '600px';
  friendsTable.class = 'table';
  friendsTable.cellspacing = '2';
  addFriendRow(tbody, '<td colspan="3"><b>Challenge your friends</b></td>');
  var friendsWithApp = [];
  var friendsWithoutApp = [];
  Penalty.friends.each(function(friend){
    var friendInfo = createFriendData(friend);
	if (Penalty.hasApp[friend.getId()]) {
		friendsWithApp.push(friendInfo);
	} else {
		friendsWithoutApp.push(friendInfo);
	}
  });
  renderFriends(friendsWithApp, tbody);
  renderFriends(friendsWithoutApp, tbody);
  //addFriendRow(tbody, getFriendDescription(friend) + msg, button);
  document.getElementById('friends').innerHTML = '<br>';  
  document.getElementById('friends').appendChild(friendsTable);
  document.getElementById('friends').style.display = 'block';
}

function addStatsRow(tbody, innerTable) {
  var tr = document.createElement('tr');
  tbody.appendChild(tr);
  var td = document.createElement('td');
  tr.appendChild(td);
  td.appendChild(innerTable);
}

function renderFriends(friends, tbody) {
  var rowNum = 1;
  var rowContent = '';
  for (var i = 0; i < friends.length; i++) {
  	if (i / 3 == rowNum) {
		addFriendRow(tbody, rowContent);
		rowContent = '';
		rowNum++;
	}
  	if (i / 3 < rowNum) {
		rowContent += '<td>' + friends[i] + '</td>';
	} 
  }
  if (rowContent != '') {
  	addFriendRow(tbody, rowContent);
  }
}

function addFriendRow(tbody, content) {
  var tr = document.createElement('tr');
  tbody.appendChild(tr);
  tr.innerHTML = content;
  /*var tdName = document.createElement('td');
  tr.appendChild(tdName);
  tdName.innerHTML = name;
  var tdButton = document.createElement('td');
  tr.appendChild(tdButton);
  tdButton.innerHTML = button;*/
}

function createFriendData(friend) {
	var content = '<table>';
	if (Penalty.hasApp[friend.getId()]) {
	  content += '<tr><td align="center"><img src="' + friend.getField(opensocial.Person.Field.THUMBNAIL_URL) 
            + '"/></td></tr>'
      content += '<tr><td>' + friend.getDisplayName() + '</td></tr>';
	  if (!isChallenged(friend.getId())) {
	  	content += '<tr>' + createButton('challenge(\'' + friend.getId() + '\');', 'Challenge') + '</tr>';
      }
    } else {
	  content += '<tr><td><img src="' + friend.getField(opensocial.Person.Field.THUMBNAIL_URL) 
	        + '"/></td></tr>'
	  content += '<tr><td>' + friend.getDisplayName() 
	  		+ ' <i> doesn\'t have Penalty shoots installed! </i></td></tr>';
    }
	return content + '</table>'
}

function getFriendDescription(friend) {
	var desc = '<tr><td><img src="' + friend.getField(opensocial.Person.Field.THUMBNAIL_URL) 
            + '"/></td></tr>';
	desc += '<tr><td>' + friend.getDisplayName() + '</td></tr>';
	return desc;
}

function isChallenged(id){
  if (!Penalty.myPenalties) {  
    return false;    
  }
  for (var friendId in Penalty.myPenalties) {
    if (friendId == id && Penalty.myPenalties[friendId]) {   
      for (var i = 0; i < Penalty.myPenalties[friendId].length; i++) { 
        if (Penalty.myPenalties[friendId][i] && 
            Penalty.myPenalties[friendId][i].type == 'SHOOT') {
          return true;
        }
      }   
    }
  }
  return false;
}

function showNotifications(){
  var displayNotifications = [];

  var notificationsTitle = "No penalty news from your friends!";
  if (Penalty.notifications) {
  	notificationsTitle = "Notifications";
    for (var i = 0; i < Penalty.notifications.length; i++) {
      displayNotifications.push(renderNotification(Penalty.notifications[i]));
    }
  }
  var notificationsHTML = '<table width="600px" class="table"><tr><td><b>' + notificationsTitle + '</b></td></tr><tr><td><table>';
  notificationsHTML += displayNotifications.join('\n') + '</table></td></tr></table>';
  document.getElementById('notifications').innerHTML = notificationsHTML;
  document.getElementById('notifications').style.display = 'block';
}

function renderNotification(notification) {
  var row = '<tr>';
  if (notification.type && notification.type != 'N/A') {
    row += '<td><table><tr><td><img src="' 
            + notification.friend.getField(opensocial.Person.Field.THUMBNAIL_URL) 
            + '"/></td><td>';
  }
  switch(notification.type) {
  	case 'PENDING_SHOT':
      row += 'You shot the ball to ' 
          + notification.friend.getDisplayName() +
          ' but he hasn\'t accepted your challenge yet!</td><tr></table></td>';
  		break;
  	case 'FRIEND_BLOCKED':
      row += notification.friend.getDisplayName() +
          ' blocked your shot!</td>';
		  break;
    case 'MY_GOAL':
      row += '<span style=""><b>GOAL!!!</b> <span>' + notification.friend.getDisplayName() +
          ' wasn\'t able to block your shot!!</td><tr></table></td>';        
      break;
    case 'ME_BLOCKED':
      row += 'You successfully blocked ' + notification.friend.getDisplayName() +
          '\'s shot!</td><tr></table></td>';
      break;
    case 'FRIEND_GOAL':
      row += 'You were not able to block this shot: ' + notification.friend.getDisplayName() +
          ' scored a goal!</td><tr></table></td>';
      break;   
    case 'CHALLENGE':
      row += notification.friend.getDisplayName() +
        ' has challenged you!</td><tr></table><td>&nbsp;</td><td>' 
        + createButton('acceptChallenge(\'' +
        notification.friend.getId() +'\',' + notification.friendsAction.id + ')', 'accept challenge!') + '</td>';
      break;
  }
  row += '</tr>';
  return row;
}

function createButton(action, message) {
  return '<span class="grabtn"><a href="javascript:void(0)"' 
    + ' onclick="' + action + '"class="btn">' + message + '</a></span>'
    + '<span class="btnboxr"><img width="5" height="1" src="http://www.orkut.com/img/castro/b.gif"/></span>';
 }
        
function challenge(friendId){
  //hideAll();
  penaltygame.friendId = friendId;
  penaltygame.goToPlayGround(penaltygame.SHOOT, Penalty.friendsMap[friendId].getDisplayName());
}

function acceptChallenge(friendId, shotId){
  //hideAll();
  penaltygame.friendId = friendId;
  penaltygame.shotId = shotId;
  penaltygame.goToPlayGround(penaltygame.CATCH, Penalty.friendsMap[friendId].getDisplayName());
}

function storeAction(action, who, position, shotId){
  if (!Penalty.myPenalties) {
    Penalty.myPenalties = {};
  }
  actionToStore = new Action(shotId ? shotId : new Date().getTime(), 
    action, position);
  if (!Penalty.myPenalties[who]) {
    Penalty.myPenalties[who] = [];
  }
  Penalty.myPenalties[who].push(actionToStore);
  var req = opensocial.newDataRequest();
  req.add(req.newUpdatePersonAppDataRequest('VIEWER', 'penalties', toData(Penalty.myPenalties)));
  prepareDefaultDataRequest(req);
  log('sending: ' + Penalty.myPenalties);
  req.send(function(response){
    penaltygame.returnToMain();
    onLoadData(response);
  });
}

function toData(obj){
  return gadgets.json.stringify(obj);
}

function log(text){
  document.getElementById('log').innerHTML += 'debug: ' + text + '<br>';
}

function hideAll(){
  document.getElementById('playground_shoot').style.display = 'none';
  document.getElementById('playground_block').style.display = 'none';
  document.getElementById('notifications').style.display = 'none';
  document.getElementById('stats').style.display = 'none';
}

function storeIfDirty(){
  if (Penalty.dirty) {
    var req = opensocial.newDataRequest();
    req.add(req.newUpdatePersonAppDataRequest('VIEWER', 'penalties', toData(Penalty.myPenalties)));
    req.send(function(response){
      Penalty.dirty = false;
    });
  }
}

function clearAppData(){
  var req = opensocial.newDataRequest();
  req.add(req.newUpdatePersonAppDataRequest('VIEWER', 'penalties', {}));
  req.send(function(response){
    log('clearAppData hadError = ' + response.hadError());
  });
}

function clearStatsData(){
  var req = opensocial.newDataRequest();
  req.add(req.newUpdatePersonAppDataRequest('VIEWER', 'stats', {}));
  req.send(function(response){
    log('clearStatsData hadError = ' + response.hadError());
  });
}

 function postActivity(text) {  
    var params = {};  
    params[opensocial.Activity.Field.TITLE] = text;
    var activity = opensocial.newActivity(params);
    opensocial.requestCreateActivity(activity, opensocial.CreateActivityPriority.LOW);
  };     
